#pragma once
#include <iostream>
#include <memory>
#include <unistd.h>
#include "Socket.hpp"
#include "Log.hpp"

using namespace SocketModule;
using namespace LogModule;

class SelectServer
{
    // fd_set 的位数（通常为1024，这里简化）
    const static int size=sizeof(fd_set)*8;
    // 默认无效文件描述符
    const static int defaultfd=-1;
    public:
        // 构造函数：初始化监听Socket和fd数组
        SelectServer(int port)
        // 创建TCP Socket
        :_listensock(std::make_unique<TcpSocket>()),
        // 服务运行标志
        _isrunning(false)
        {
            // 绑定端口并监听
            _listensock->BuildTcpSocketMethod(port);
            for(int i=0;i<size;i++)
            {
            // 初始化fd数组为无效值
            _fd_array[i]=defaultfd;
            // 将监听Socket加入数组
            _fd_array[0]=_listensock->Fd();
            }
        }
        //主事件循环 
        void Start()
        {
            _isrunning=true;
            while(_isrunning==true)
            {
                // 定义读事件集合
                fd_set rfds;
                // 清空集合
                FD_ZERO(&rfds);
                // 记录当前最大fd
                int maxfd=defaultfd;
                // 步骤1：将所有有效fd加入select监控
                 for(int i=0;i<size;i++)
                {
                    if(_fd_array[i]==defaultfd) continue;
                    // 加入监控集合
                    FD_SET(_fd_array[i],&rfds);
                    // 更新最大fd
                    if(maxfd<_fd_array[i])
                    maxfd=_fd_array[i];
                }
                 // 调试：打印当前监控的fd
            PrintFd();
                // 步骤2：调用select阻塞等待事件
                int n=select(maxfd+1,&rfds,nullptr,nullptr,nullptr);
                switch (n)
                {
                // 错误处理
                case -1:
                    LOG(LogLevel::ERROR)<<"select error";
                    break;
                // 超时（未设置超时参数，通常不触发）
                case 0:
                    LOG(LogLevel::INFO)<<"timeout...";
                    break;
                // 事件就绪
                default:
                    LOG(LogLevel::DEBUG) << "有事件就绪, n: " << n;
                    //处理分发事务
                    Dispatcher(rfds);
                    break;
                }
            }
           // 停止服务
           _isrunning=false;
        }
        //事件分发器 
        void Dispatcher(fd_set &rfds)
        {
            for(int i=0;i<size;i++)
            {
                if(_fd_array[i]==defaultfd) continue;
            // 检查fd是否读就绪
                if(FD_ISSET(_fd_array[i],&rfds))
                {
                    if(_fd_array[i]==_listensock->Fd())
                    {
                        // 监听Socket就绪：接受新连接
                        Accepter();
                    }else{
                        // 普通Socket就绪：读取数据
                        Recver(_fd_array[i],i);
                    }
                    
                }
        }
            
        }
        //新连接处理
        void Accepter()
        {
            InetAddr client;
            // 接受新连接
            int sockfd=_listensock->Accept(&client);
            if(sockfd>=0)
            {
                 LOG(LogLevel::INFO) << "新连接: sockfd=" << sockfd 
                           << ", 客户端=" << client.StringAddr();

                // 将新fd存入_fd_array的空位
                int pos=0;
                for( ;pos<size;pos++)
                {
                    if(_fd_array[pos]==defaultfd) break;
                }
                // 数组已满
                if(pos==size)
                {
                    LOG(LogLevel::WARNING) << "select server已满";
                    close(sockfd);
                }else
                {
                    // 托管给select监控
                    _fd_array[pos]=sockfd;
                }
            }
        }
        //数据读取处理 
        void Recver(int fd,int pos)
        {
            char buffer[1024];
            // 读取数据
            ssize_t n=recv(fd,buffer,sizeof(buffer)-1,0);
            // 正常数据
            if(n>0)
            {
                buffer[n] = 0;
                std::cout << "客户端消息: " << buffer << std::endl;
            }
            // 客户端关闭连接
            else if(n==0)
            {
                 LOG(LogLevel::INFO) << "客户端退出";
                  // 从监控数组移除
                  _fd_array[pos]=defaultfd;
                  close(fd);
            }

        }
        // 打印当前监控的fd（调试用）
        void PrintFd()
        {
            std::cout << "监控的fd: ";
            for (int i = 0; i < size; i++) 
            {
            if (_fd_array[i] == defaultfd) continue;
                std::cout << _fd_array[i] << " ";
             }
                std::cout << "\n";
        }
        //停止服务
        void Stop()
        {
            _isrunning=false;
        }
        ~SelectServer()
        {}
    private:
        //理监听Socket对象的生命周期
        std::unique_ptr<Socket> _listensock;
        //服务器的运行状态
        bool _isrunning;
        //一个固定大小的整数数组，存储所有需要被 select() 监控的文件描述符（fd）
        int _fd_array[size];
};